package cuongnh.project.japanesediary.vocabulary.ui.view;

import java.util.Set;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.observable.set.IObservableSet;
import org.eclipse.core.databinding.property.Properties;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.databinding.viewers.ObservableSetTreeContentProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.internal.PluginActionContributionItem;
import org.eclipse.wb.rcp.databinding.BeansSetObservableFactory;
import org.eclipse.wb.rcp.databinding.TreeBeanAdvisor;
import org.eclipse.wb.rcp.databinding.TreeObservableLabelProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import cuongnh.coreframework.ui.workbench.common.view.AutoUpdateView;
import cuongnh.project.japanesediary.vocabulary.common.CommonServices;
import cuongnh.project.japanesediary.vocabulary.model.Category;

@Component("categoryListView")
@Scope("prototype")
public class CategoryListView extends AutoUpdateView {
	private DataBindingContext m_bindingContext;

	public static final String ID = "cuongnh.project.japanesediary.vocabulary.ui.view.CategoryListView"; //$NON-NLS-1$
	private final FormToolkit toolkit = new FormToolkit(Display.getCurrent());
	private Set<Category> parentCategories;
	private Category selectedCategory;
	@Autowired
	private CommonServices commonServices;
	private TreeViewer tblvCategoryList;
	private Section sctnCategories;

	public CategoryListView() {
	}

	/**
	 * Create contents of the view part.
	 * 
	 * @param parent
	 */
	@Override
	public void createPartControl(Composite parent) {
		Composite container = toolkit.createComposite(parent, SWT.NONE);
		toolkit.paintBordersFor(container);
		container.setLayout(new GridLayout(1, false));
		sctnCategories = toolkit.createSection(container, Section.TITLE_BAR);
		GridData gd_sctnCategories = new GridData(SWT.FILL, SWT.FILL, true,
				true, 1, 1);
		gd_sctnCategories.widthHint = 165;
		sctnCategories.setLayoutData(gd_sctnCategories);
		toolkit.paintBordersFor(sctnCategories);
		sctnCategories.setText("Categories");
		sctnCategories.setExpanded(true);
		Composite composite1 = new Composite(sctnCategories, SWT.NONE);
		toolkit.adapt(composite1);
		toolkit.paintBordersFor(composite1);
		sctnCategories.setClient(composite1);
		composite1.setLayout(new GridLayout(1, false));

		tblvCategoryList = new TreeViewer(composite1, SWT.BORDER);
		Tree treeCategories = tblvCategoryList.getTree();
		GridData gd_treeCategories = new GridData(SWT.FILL, SWT.FILL, true,
				true, 1, 1);
		gd_treeCategories.widthHint = 232;
		treeCategories.setLayoutData(gd_treeCategories);
		toolkit.paintBordersFor(treeCategories);

		createActions();
		initializeMenu();
		initContextMenu();
		getSite().setSelectionProvider(tblvCategoryList);

		tblvCategoryList
				.addSelectionChangedListener(new ISelectionChangedListener() {

					@Override
					public void selectionChanged(SelectionChangedEvent event) {
						IStructuredSelection ssel = (IStructuredSelection) event
								.getSelection();
						if (ssel.size() == 1) {
							selectedCategory = (Category) ssel
									.getFirstElement();
						}

					}
				});

		initData();
		m_bindingContext = initDataBindings();
	}

	private void initData() {
		parentCategories = commonServices.getCategoryDao()
				.getAllParentWithSubCategories();
	}

	/**
	 * Create the actions.
	 */
	private void createActions() {
		// Create the actions
	}

	public void refresh() {
		parentCategories.clear();
		parentCategories.addAll(commonServices.getCategoryDao()
				.getAllParentWithSubCategories());
		m_bindingContext.updateModels();
		tblvCategoryList.refresh();
	}

	/**
	 * Initialize the menu.
	 */
	private void initializeMenu() {
		IMenuManager manager = getViewSite().getActionBars().getMenuManager();
	}

	private void initContextMenu() {
		MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				CategoryListView.this.fillContextMenu(manager);
			}
		});
		Menu menu = menuMgr.createContextMenu(tblvCategoryList.getControl());
		tblvCategoryList.getControl().setMenu(menu);
		getSite().registerContextMenu(menuMgr, tblvCategoryList);
	}

	private void fillContextMenu(IMenuManager manager) {
		IActionBars bars = getViewSite().getActionBars();

		ContributionItem item;
		for (int index = 0; index < bars.getToolBarManager().getItems().length; index++) {
			item = (ContributionItem) bars.getToolBarManager().getItems()[index];
			if (!item.isSeparator()) {
				manager.add(((PluginActionContributionItem) item).getAction());
			}else{
				manager.add(new Separator());
			}

		}

		// Other plug-ins can contribute there actions here
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
	}

	protected DataBindingContext initDataBindings() {
		DataBindingContext bindingContext = new DataBindingContext();
		//
		BeansSetObservableFactory treeObservableFactory = new BeansSetObservableFactory(
				Category.class, "subCategories");
		TreeBeanAdvisor treeAdvisor = new TreeBeanAdvisor(Category.class,
				"parentCategory", "subCategories", null);
		ObservableSetTreeContentProvider treeContentProvider = new ObservableSetTreeContentProvider(
				treeObservableFactory, treeAdvisor);
		tblvCategoryList.setLabelProvider(new TreeObservableLabelProvider(
				treeContentProvider.getKnownElements(), Category.class,
				"categoryName", null));
		tblvCategoryList.setContentProvider(treeContentProvider);
		//
		IObservableSet selfSet = Properties.selfSet(Category.class).observe(
				parentCategories);
		tblvCategoryList.setInput(selfSet);
		//
		return bindingContext;
	}

	public CommonServices getCommonServices() {
		return commonServices;
	}

	public Category getSelectedCategory() {
		return selectedCategory;
	}

	public TreeViewer getTblvCategoryList() {
		return tblvCategoryList;
	}

	public Set<Category> getParentCategories() {
		return parentCategories;
	}

	@Override
	public void update() {
		refresh();
	}
}
